package test.fingers;
/**
 * @author Jesse McCane
 * @author Berkley Shands
 */

/*
 * This class deals with all player related functionality that is the same between computer
 * and human players.
 */

import java.util.ArrayList;

public abstract class Player{
	protected static int playerCount = 1; //used as ID numbers for unnamed players
	protected static int compCount = 1;
	protected static int totalCount = 0;

	protected int tricksBid = -1;
	protected int suitBid = -1;
	protected int callType = -1;

	protected int tricksTaken = 0;
	protected int score = 0;
	protected int rScore = 0;

	protected int nilValue = 50;

	protected ArrayList<Card> myHand;
	protected ArrayList<Boolean> playableCards;
	protected String myName;

	protected int myIDNum;

	//clears old hands and deals a new hand
	public void receiveHand(Card hand[]){
		int numCards = hand.length;
		myHand = new ArrayList<Card>();

		for(int i = 0; i < numCards; i++){
			myHand.add(i, hand[i]);
		}
		myHand = Sort.sortHand(myHand);
	}

	//displays the players hand
	public void displayHand(){
		System.out.println(myName + "'s hand:");
		for(int i = 0; i < myHand.size(); i++){
			System.out.println("" + (i + 1) + " - " + myHand.get(i).toString());
		}
		System.out.println("");
	}

	public void displayPlayableHand(){}
	
	public String[] getHand(){
		String[] retStr = new String[myHand.size()];
		
		for(int i=0; i<myHand.size(); i++){
			retStr[i] = myHand.get(i).toString();
		}
		
		return retStr;
	}

	//these will get changed when we implement scoring
	public void addScore(int score){
		this.score += score;
	}

	public int getScore(){
		return score;
	}

	/**
	 * @return the tricksBid
	 */
	public int getTricksBid(){
		return tricksBid;
	}

	/**
	 * Sets the tricks taken variable
	 */
	public void setTricksBid(int tricks){
		this.tricksBid = tricks;
	}

	/**
	 * Adds to the tricks taken variable
	 */
	public void addTricksTaken(){
		this.tricksTaken++;
	}

	/**
	 * @return the tricksTaken
	 */
	public int getTricksTaken(){
		return tricksTaken;
	}

	/**
	 * Returns the player name
	 */
	public String getMyName(){
		return myName;
	}

	public int getSuitBid(){
		return suitBid;
	}

	public void setSuitBid(int suitBid){
		this.suitBid = suitBid;
	}

	public int getCallType(){
		return callType;
	}

	public void setCallType(int callType){
		this.callType = callType;
	}

	public void setBidParams(int callType, int tricksBid, int trumpBid){
		this.callType = callType;
		this.suitBid = trumpBid;
		this.tricksBid = tricksBid;
	}

	//resets bidding variables for a new round
	public void newRound(){
		this.suitBid = -1;
		this.tricksBid = -1;
		this.callType = -1;
		this.tricksTaken = 0;
		this.rScore = this.score;
	}

	protected Card playCard(int cardNum){
		Card retCard = myHand.remove(cardNum);
		return retCard;
	}

	public boolean hasSuit(int checkSuit){
		for(int i = 0; i < myHand.size(); i++){
			if(myHand.get(i).getSuit() == checkSuit){
				return true;
			}
		}
		return false;
	}

	public boolean handHasAOH(){
		for(int i = 0; i < myHand.size(); i++){
			if(myHand.get(i).isAOH()){
				return true;
			}
		}
		return false;
	}

	public void setPlayableCards(Card[] cardsPlayed, int firstCard, int numPlayed){}

	public int scoreSelf(){
		int missedHands;
		int offPoints = 0;

		if(callType == Gameplay.PASS){ //passed so no need to worry about hands made
			return 0;
		}

		if(callType == Gameplay.NIL){ //you niller
			if(tricksTaken != 0){
				this.addScore(tricksTaken * -10);
			}else{
				this.addScore(nilValue); //have to add variable to track past nils..and increase score accordingly
			}
			return 0;
		}

		//we know they bid something at this point
		missedHands = Math.abs(tricksTaken - tricksBid);

		if(tricksTaken > tricksBid){ //made more than bid
			offPoints = missedHands * 5;
			this.addScore(tricksBid * 10 - offPoints);
		}else if(tricksTaken < tricksBid){//didnt make bid
			offPoints = missedHands * 10;
			this.addScore(-1 * offPoints);
		}else{
			this.addScore(tricksBid * 10);
		}

		return offPoints;
	}

	public void displayResults(){
		if(callType == Gameplay.NIL){ //player niled
			if(tricksTaken > 0){ //didnt make the nil
				System.out.println(myName + " niled but took " + tricksTaken + " trick(s)");
			}else{
				System.out.println(myName + " made their nil");
			}
		}else if(callType == Gameplay.PASS){
			System.out.println(myName + " passed");
		}else{
			System.out.println(myName + " bid " + tricksBid + " trick(s) and took " + tricksTaken);
		}
	}

	public int getRoundScore(){
		return(score - rScore);
	}

	public abstract void firstBid();

	public abstract int bid(int maxTrump, int maxBid, int bCounter);

	protected void doCall(int maxTrump, int maxBid){
		int tempCall;
		if(maxBid == 0){
			tempCall = Gameplay.NIL;
		}else{
			tempCall = Gameplay.BID;
		}

		this.setBidParams(tempCall, maxBid, maxTrump);
	}

	protected void doPass(){
		this.setBidParams(Gameplay.PASS, -1, -1);
	}

	protected abstract boolean doBid(int maxTrump, int maxBid);

	protected abstract boolean doNil(int maxTrump, int maxBid);

	//playTrick has every player play a card. The winner of the trick is then determined,
	//and the winning player's tricksTaken is incremented
	public abstract Card playTrick();

	public abstract void determineStrat();//used for computer ai

	public abstract void adjustRoundStrat();//used for computer ai

	public boolean equals(Player plyer){
		if(this.myIDNum == plyer.getMyID()){
			return true;
		}

		return false;
	}

	//returns unique id number
	protected int getMyID(){
		return myIDNum;
	}
}
